﻿@inherits BaseComponent

@if (IsButton)
{
    <div class="kui-upload">
        @if (!ReadOnly)
        {
            <div class="kui-button">
                <KIcon Icon="upload" />
                <span>@Language.Upload</span>
                <InputFile multiple="@IsMultiple" webkitdirectory="@Directory" OnChange="OnInputFileChangedAsync" />
            </div>
        }
        @BuildFiles
    </div>
}
else
{
    if (!ReadOnly)
    {
        <InputFile multiple="@IsMultiple" webkitdirectory="@Directory" OnChange="OnInputFileChangedAsync" />
    }
    @BuildFiles
}

@code {
    private List<AttachInfo> sysFiles = [];
    private readonly List<FileDataInfo> files = [];
    private bool IsMultiple => MultiFile || Directory;

    private RenderFragment BuildFiles => @<div class="kui-form-files">
        @foreach (var item in sysFiles)
        {
            var url = item.FileUrl;
            <div>
                @if (!ReadOnly)
                {
                    <span class="kui-link kui-danger" @onclick="e=>OnDeleteFile(item)">@Language.Delete</span>
                }
                <FileLink Item="item" />
            </div>
        }
    </div>
    ;

    /// <summary>
    /// 取得或设置是否显示上传按钮。
    /// </summary>
    [Parameter] public bool IsButton { get; set; }

    /// <summary>
    /// 取得或设置上传组件关联字段值。
    /// </summary>
    [Parameter] public string Value { get; set; }

    /// <summary>
    /// 取得或设置上传组件是否支持多文件上传。
    /// </summary>
    [Parameter] public bool MultiFile { get; set; }

    /// <summary>
    /// 取得或设置上传组件是否支持文件夹上传。
    /// </summary>
    [Parameter] public bool Directory { get; set; }

    /// <summary>
    /// 取得或设置上传组件文件改变事件委托。
    /// </summary>
    [Parameter] public Func<List<FileDataInfo>, Task> OnFilesChanged { get; set; }

    /// <summary>
    /// 取得或设置上传组件获取文件列表委托。
    /// </summary>
    [Parameter] public Func<string, Task<List<AttachInfo>>> OnLoad { get; set; }

    /// <summary>
    /// 取得或设置上传组件删除文件委托。
    /// </summary>
    [Parameter] public Func<AttachInfo, Task> OnDelete { get; set; }

    /// <summary>
    /// 刷新上传组件内容。
    /// </summary>
    /// <returns></returns>
    public override async Task RefreshAsync()
    {
        if (string.IsNullOrWhiteSpace(Value))
            return;

        if (OnLoad != null)
            sysFiles = await OnLoad.Invoke(Value);
        else
            sysFiles = await Platform.GetFilesAsync(Value);
        await StateChangedAsync();
    }

    /// <summary>
    /// 异步设置上传组件关联字段值。
    /// </summary>
    /// <param name="value">附件字段值。</param>
    public async Task SetValueAsync(string value)
    {
        Value = value;
        await RefreshAsync();
    }

    /// <summary>
    /// 上传组件呈现后，调用后端接口加载附件列表。
    /// </summary>
    /// <param name="firstRender">是否首次呈现。</param>
    /// <returns></returns>
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);
        if (firstRender)
            await RefreshAsync();
    }

    private async Task OnInputFileChangedAsync(InputFileChangeEventArgs e)
    {
        var isChange = false;
        if (MultiFile || Directory)
        {
            foreach (var item in e.GetMultipleFiles())
            {
                isChange = await OnAddFileAsync(item);
            }
        }
        else
        {
            isChange = await OnAddFileAsync(e.File);
        }

        if (isChange)
        {
            await StateChangedAsync();
            await OnFilesChanged?.Invoke(files);
        }
    }

    private async Task<bool> OnAddFileAsync(IBrowserFile item)
    {
        if (files.Exists(f => f.Name == item.Name))
            return false;

        var file = await item.CreateFileAsync();
        files.Add(file);
        sysFiles ??= [];
        sysFiles.Add(new AttachInfo { Id = "", Name = item.Name });
        return true;
    }

    private void OnDeleteFile(AttachInfo item)
    {
        if (string.IsNullOrWhiteSpace(item.Id))
        {
            var file = files.FirstOrDefault(f => f.Name == item.Name);
            files.Remove(file);
            sysFiles?.Remove(item);
            OnFilesChanged?.Invoke(files);
            return;
        }

        var message = Language["Tip.ConfirmDelete"].Replace("{name}", item.Name);
        UI.Confirm(message, async () =>
        {
            if (OnDelete != null)
                await OnDelete.Invoke(item);
            else
                await Platform.DeleteFileAsync(item);
            sysFiles?.Remove(item);
            await StateChangedAsync();
        });
    }
}